package com.huobi.pro.trade;

import java.math.BigDecimal;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import com.huobi.db.bean.HbLineData;
import com.huobi.db.bean.PlaceInfo;
import com.huobi.db.bean.TradeOrder;
import com.huobi.db.mapper.TradeOrderMapper;
import com.huobi.event.LineDataEvent;
import com.huobi.pro.mirror.TradeMirrorService;
import com.huobi.pro.trade.rep.BuyResult;
import com.huobi.pro.trade.rep.CancelResult;
import com.huobi.pro.trade.rep.QryResult;
import com.huobi.pro.trade.utils.SnowFlake;

import lombok.Getter;

@Service
public class TradeService {

	@Autowired TradeOrderMapper tradeOrderMapper;
	@Autowired BuyService buy;
	@Autowired TradeMirrorService tradeMirrorService;

	@EventListener
	public void onApplicationEvent(LineDataEvent event) {

		final HbLineData[] arrays = event.getData();
		final HbLineData data = arrays[arrays.length - 1];

		tradeMirrorService.push(data.getTradeDate(),data.getHigh(),data.getLow());
		
		if (tradeMirrorService.trade()) {
			// 获取最后一条订单
			TradeOrder order = getLastTradeOrder(Status.SUCCED);
			if (order == null) { // 没有交易过
				newTrade(data.getClose());
				return;
			}
		}
	}

	public TradeOrder getLastTradeOrder(Status status) {
		TradeOrder order = tradeOrderMapper.getLastTradeOrder(status.value);
		return order;
	}
	
	// 发起新的交易
	public void newTrade(final BigDecimal price) {
		// 存在没成交的订单
		if (getLastTradeOrder(Status.PENDING) != null) {
			return;
		}
		if (getLastTradeOrder(Status.WAITING) != null) {
			return;
		}
		// 测试代码
		BigDecimal vv = price.subtract(price.multiply(BigDecimal.valueOf(0.01)));
		trade(newOrder(vv));
	}

	// 查询挂单
	public void queryOrder(String orderid) {
		TradeOrder order = tradeOrderMapper.findById(orderid);
		if (!Status.PENDING.value.equals(order.getStatus()))
			return;
		QryResult result = buy.order(order.getHuobiOrder());
		if(!result.isSuccess())
			return;
		final PlaceInfo placeinfo = new PlaceInfo();
		// 先看看有没有成交的
		BigDecimal tradeAmount = result.getTradeAmount();
		// 部分成交
		if (tradeAmount.compareTo(BigDecimal.ZERO) > 0) {
			placeinfo.setDealAmount(tradeAmount);
			if (tradeAmount.compareTo(order.getAmount()) == 0) {
				placeinfo.setStatus(Status.SUCCED.getValue());
			}else {
				placeinfo.setStatus(Status.PARTIAL_SUCCED.getValue());
			}
		}
		placeinfo.setHuobiOrderStatus(result.getTradeStatus());
		placeinfo.setId(order.getId());
		tradeOrderMapper.updateInfo(placeinfo);
	}
	
	// 取消订单
	public void cannelOrder(String orderid) {
		TradeOrder order = tradeOrderMapper.findById(orderid);
		// 取消订单
		CancelResult cancel = buy.cancel(order.getHuobiOrder());
		if("7".equals(cancel.getOrderState())) {
			tradeOrderMapper.updateToFailed(order.getId());
		}else if("5".equals(cancel.getOrderState())) {
			tradeOrderMapper.updateToPSucced(order.getId());
		}
		// 补查询
		queryOrder(orderid);
	}

	//根据订单进行交易
	public void trade(String orderid) {
		TradeOrder order = tradeOrderMapper.findById(orderid);
		// 下单
		if (1 == tradeOrderMapper.updateToPending(order.getId())) {
			BuyResult result = buy.buy(order.getId(), order.getAmount(), order.getPrice());
			if (result.isSuccess()) {
				// 操作成功了，但是不一定成交了
				final PlaceInfo placeinfo = new PlaceInfo();
				placeinfo.setHuobiOrder(result.getHuobiOrderId());
				placeinfo.setId(order.getId());
				tradeOrderMapper.updateInfo(placeinfo);
			} else {
				tradeOrderMapper.updateToWaiting(order.getId());
			}
		}
	}
	
	private String newOrder(BigDecimal price) {
		TradeOrder order = new TradeOrder();
		order.setAmount(BigDecimal.valueOf(200));
		order.setPrice(price);
		order.setDirection(Direction.BUY.value);
		order.setStatus(Status.WAITING.value);
		order.setCreateDate(new Date());
		order.setAveragePrice(BigDecimal.ZERO);
		order.setId(SnowFlake.self().nextStringId());
		tradeOrderMapper.save(order);
		return order.getId();
	}

	public enum Direction{
		BUY("buy"),
		SELL("sell");
		@Getter
		private String value;
		private Direction(String value) {
			this.value= value;
		}
	}
	
	public enum Status{
		WAITING("waiting"),
		PENDING("pending"),
		PARTIAL_SUCCED("p_succed"),
		SUCCED("succed"),
		FAILED("failed"); 
		@Getter
		private String value;
		private Status(String value) {
			this.value= value;
		}
	}

}
